package app.scraper.textyard;

/**
 *
 * @author Mature Dev Team
 */
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import org.apache.commons.logging.LogFactory;
import org.apache.http.NoHttpResponseException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.w3c.css.sac.CSSException;
import org.w3c.css.sac.CSSParseException;
import org.w3c.css.sac.ErrorHandler;

import app.scraper.textyard.model.Book;
import app.scraper.textyard.model.Course;
import app.scraper.textyard.model.Department;
import app.scraper.textyard.model.Section;
import app.scraper.textyard.model.Term;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.CookieManager;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.IncorrectnessListener;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.ProxyConfig;
import com.gargoylesoftware.htmlunit.ScriptException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.html.HTMLParserListener;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.javascript.JavaScriptErrorListener;
import com.gargoylesoftware.htmlunit.util.Cookie;
import com.gargoylesoftware.htmlunit.util.NameValuePair;
import com.gargoylesoftware.htmlunit.util.WebConnectionWrapper;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

public class Scraper extends Thread {

	private static final int READ_TIMEOUT = 15000;
	public static final int BLOCKED_TIMEOUT = 480;
	private static final String COMMA_URL_CODE = "%2C";
	private static final int LIMIT = 3;
	private static int COUNT = 0;
	private WebClient web;
	public String link = "http://www.textyard.com/";
	HtmlPage page = null;
	public JComboBox school;
	public JTable depart;
	List<HtmlElement> schools = null;
	public JProgressBar bar;
	List<HtmlElement> depa = null;
	public JTable t_depar;
	public List<Integer> selection = null;
	public JProgressBar bar2 = null;
	public int school_index = 0;
	public String file_name;
	private TreeMap<String, String> schoolMap = new TreeMap<String, String>();
	private TreeMap<Department, ArrayList<Book>> resultMap = new TreeMap<Department, ArrayList<Book>>();
	private String ajaxBase = "http://www.textyard.com/ajax/dropdown_ajax.php?c=";
	private List<Department> departments;
	private String sessId;
	private URL postSearchUrl = null;
	private URL postRemoveUrl = null;
	private int processedClasses = 0;

	public interface StatusPostable {
		void postStatusIPBlocked();

		void postBreaking();

		void postProgress(int val);

		void postPastLimitError();
		
		void postErrorMsg(String msg);
	}

	private StatusPostable status;

	private BrowserVersion[] browserVersionChain = new BrowserVersion[] { BrowserVersion.FIREFOX_10,
			BrowserVersion.CHROME_16, BrowserVersion.INTERNET_EXPLORER_7, BrowserVersion.FIREFOX_3_6,
			BrowserVersion.INTERNET_EXPLORER_8 };
	private boolean noMoreProxies;
	private int errorCount;
	private Properties proxyHostsPros;
	private int nextProxy = 0;
	private boolean useProxy;
	private String outputFile;
	private static int browserIndex = 0;

	private static int postSearchCount = 0;
	private static int postRemoveCount = 0;
	private ResultsExporter resultExporter;

	@Override
	public void run() {
		load_page();
	}

	public Scraper() {
		try {
			postSearchUrl = new URL("http://www.textyard.com/ajax/search_ajax.php");
			postRemoveUrl = new URL("http://www.textyard.com/ajax/remove_ajax.php");
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}

		LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log",
				"org.apache.commons.logging.impl.NoOpLog");

		java.util.logging.Logger.getLogger("com.gargoylesoftware.htmlunit").setLevel(Level.OFF);
		java.util.logging.Logger.getLogger("org.apache.commons.httpclient").setLevel(Level.OFF);

		createNewWebClient();
	}

	private void createNewWebClient() {
		web = null;
		web = new WebClient(getNextBrowserVersion());
		web.setTimeout(READ_TIMEOUT);
		if (useProxy) {
			setProxy();
		}
		web.setWebConnection(new RetryHttpWebConnection(web));
		sessId = getSessId();
		web.setCssEnabled(false);
		web.getCookieManager().setCookiesEnabled(true);
		web.getCookieManager().addCookie(new Cookie("www.textyard.com", "PHPSESSID", sessId));

		web.setJavaScriptEnabled(true);
		web.setIncorrectnessListener(new IncorrectnessListener() {
			@Override
			public void notify(final String arg0, final Object arg1) {
				// TODO Auto-generated method stub
			}
		});
		web.setCssErrorHandler(new ErrorHandler() {
			@Override
			public void warning(final CSSParseException exception) throws CSSException {
				// TODO Auto-generated method stub
			}

			@Override
			public void fatalError(final CSSParseException exception) throws CSSException {
				// TODO Auto-generated method stub
			}

			@Override
			public void error(final CSSParseException exception) throws CSSException {
				// TODO Auto-generated method stub
			}
		});
		web.setJavaScriptErrorListener(new JavaScriptErrorListener() {
			@Override
			public void timeoutError(final HtmlPage arg0, final long arg1, final long arg2) {
				// TODO Auto-generated method stub
			}

			@Override
			public void scriptException(final HtmlPage arg0, final ScriptException arg1) {
				// TODO Auto-generated method stub
			}

			@Override
			public void malformedScriptURL(final HtmlPage arg0, final String arg1, final MalformedURLException arg2) {
				// TODO Auto-generated method stub
			}

			@Override
			public void loadScriptError(final HtmlPage arg0, final URL arg1, final Exception arg2) {
				// TODO Auto-generated method stub
			}
		});
		web.setHTMLParserListener(new HTMLParserListener() {
			@Override
			public void warning(final String arg0, final URL arg1, final int arg2, final int arg3, final String arg4) {
				// TODO Auto-generated method stub
			}

			@Override
			public void error(final String arg0, final URL arg1, final int arg2, final int arg3, final String arg4) {
				// TODO Auto-generated method stub
			}
		});
		web.setAjaxController(new NicelyResynchronizingAjaxController());
		// web.setJavaScriptEnabled(false);
		try {
			web.setUseInsecureSSL(true);
		} catch (GeneralSecurityException e) {
			e.printStackTrace();
		}
		web.setThrowExceptionOnFailingStatusCode(false);
		web.setThrowExceptionOnScriptError(false);
	}

	private void setProxy() {
		String proxyHostPort = getNextProxyHost();
		if (proxyHostPort != null) {
			String[] hostPort = proxyHostPort.split(":");
			if (isValidProxy(hostPort)) {
				web.setProxyConfig(new ProxyConfig(hostPort[0], Integer.parseInt(hostPort[1])));
			} else {
				setProxy();
			}
		} else {
			noMoreProxies = true;
			useProxy = false;
			nextProxy = 0;
		}
	}

	private boolean isValidProxy(final String[] nextProxyHost) {
		Socket s = new Socket();
		InetSocketAddress adr = new InetSocketAddress(nextProxyHost[0], Integer.parseInt(nextProxyHost[1]));

		if (adr.isUnresolved()) {
			System.out.println("The proxy " + Arrays.toString(nextProxyHost) + " is not valid");
			return false;
		}
		try {
			s.connect(adr, 10000);
			System.out.println("The proxy " + Arrays.toString(nextProxyHost) + " is OK");
			return true;
		} catch (IOException e) {
			System.out.println("The proxy " + Arrays.toString(nextProxyHost) + " is not valid");
			return false;
		} finally {
			if (s != null) {
				try {
					s.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public String getNextProxyHost() {
		if (proxyHostsPros == null) {
			proxyHostsPros = new Properties();
			try {
				proxyHostsPros.load(new FileInputStream("proxylist.props"));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return proxyHostsPros.getProperty(String.valueOf(nextProxy++));
	}

	public void load_page() {
		try {
			page = web.getPage(link);
			WebConnectionWrapper w = new WebConnectionWrapper(web);
			WebResponse schoolResp = w.getResponse(new WebRequest(new URL(
					"http://www.textyard.com/ajax/campus_ajax.php?q=a")));

			parseSchools(schoolResp);
			fillSchollCombo();

			bar.setIndeterminate(false);
			bar.setString("Schools done.");

		} catch (IOException ex) {
			JOptionPane.showMessageDialog(null, "site Down\n" + ex.getMessage());
			Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
		} catch (FailingHttpStatusCodeException ex) {
			Logger.getLogger(Scraper.class.getName()).log(Level.SEVERE, null, ex);
		}
	}

	private void parseSchools(final WebResponse schoolResp) throws IOException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(schoolResp.getContentAsStream()));
		String line;
		while ((line = reader.readLine()) != null) {
			String[] data = line.split("\\|");
			schoolMap.put(data[0], data[1]);
		}
	}

	private void fillSchollCombo() {
		for (String schoolName : schoolMap.keySet()) {
			school.addItem(schoolName);
		}
	}

	public List<Term> loadTermsForSchool(final String name) throws Exception {
		JsonObject obj = getJsonObject(ajaxBase + schoolMap.get(name));

		Gson gson = new Gson();
		List<Term> terms = new LinkedList<Term>();
		for (Entry<String, JsonElement> entry : obj.entrySet()) {
			String id = entry.getKey();
			JsonElement value = entry.getValue();
			if (value.isJsonObject()) {
				Term term = gson.fromJson(value, Term.class);
				term.setId(Integer.parseInt(id));
				term.setSchoolId(schoolMap.get(name));
				term.setSchoolName(name);
				System.out.println(term);
				terms.add(term);
			}

		}
		return terms;

	}

	public List<Department> loadDepartmentForTerm(final Term term) throws Exception {
		String deptUrl = ajaxBase + term.getSchoolID() + "&term=" + term.getId();
		JsonObject obj = getJsonObject(deptUrl);
		Gson gson = new Gson();
		departments = new LinkedList<Department>();
		int delta = (int) (1.0 / obj.entrySet().size() * 100.0);
		for (Entry<String, JsonElement> entry : obj.entrySet()) {
			String id = entry.getKey();
			JsonElement value = entry.getValue();
			if (value.isJsonObject()) {
				Department dept = gson.fromJson(value, Department.class);
				dept.setId(Integer.parseInt(id));
				dept.setTerm(term);
				dept.setCourses(loadCourseForDepartment(deptUrl + "&dept=" + dept.getId()));
				System.out.println(dept);
				departments.add(dept);
			}
			status.postProgress(delta);
		}
		return departments;
	}

	List<Course> loadCourseForDepartment(final String url) throws Exception {
		JsonObject obj = getJsonObject(url);
		Gson gson = new Gson();
		List<Course> courses = new LinkedList<Course>();
		for (Entry<String, JsonElement> entry : obj.entrySet()) {
			String id = entry.getKey();
			JsonElement value = entry.getValue();
			if (value.isJsonObject()) {
				Course course = gson.fromJson(value, Course.class);
				course.setId(Integer.parseInt(id));
				// course.setSections(loadSectionForCourse(url + "&course=" +
				// course.getId())); INVOKE LATER
				courses.add(course);
			}

		}
		return courses;
	}

	List<Section> loadSectionForCourse(final String url) throws Exception {
		JsonObject obj = getJsonObject(url);
		Gson gson = new Gson();
		List<Section> sections = new LinkedList<Section>();
		for (Entry<String, JsonElement> entry : obj.entrySet()) {
			String id = entry.getKey();
			JsonElement value = entry.getValue();
			if (value.isJsonObject()) {
				Section sect = gson.fromJson(value, Section.class);
				sect.setId(Integer.parseInt(id));
				sections.add(sect);
			}

		}
		return sections;
	}

	JsonObject getJsonObject(final String url) throws Exception {
		final WebRequest webRequest = new WebRequest(new URL(url));
		final WebResponse response = new WebConnectionWrapper(web).getResponse(webRequest);
		String responseString = response.getContentAsString();

		JsonParser parser = new JsonParser();
		JsonObject obj = parser.parse(responseString).getAsJsonObject();
		return obj;
	}

	public void sendSearchRequest() throws Exception {
		resultExporter = new ResultsExporter(outputFile);
		resultMap.clear();
		double progressDelta = (1.0 / selection.size() * 100.0);
		for (int i = 0; i < selection.size(); i++) {
			System.out.println("Selection: " + selection.get(i));
			Department d = departments.get(selection.get(i));
			System.out.println("Processing " + d.getDepCode() + " " + d.getCources());
			try {
				search(d, progressDelta);
				resultExporter.export(resultMap);
				resultMap.clear();
			} catch (NoHttpResponseException e) {
				continue;
			} catch (SocketTimeoutException e) {
				continue;
			}
		}
		if (!resultMap.isEmpty()) {
			resultExporter.export(resultMap);
		}
	}

	private void search(final Department dept, final double progressDelta) throws NoHttpResponseException, SocketTimeoutException, Exception {
		long start = System.currentTimeMillis();
		WebConnectionWrapper wrapper = new WebConnectionWrapper(web);
		final URL SEARCH_URL = new URL("http://www.textyard.com/search.php");
		CookieManager cookieMngr = web.getCookieManager();
		try {
			String schoolID = dept.getTerm().getSchoolID();
			ArrayList<Integer> classIds = getClassIds(dept);
			ArrayList<Book> books = new ArrayList<Book>();
			int size = classIds.size();
			for (int i = 0; i < size; i += 3) {
				String classIdsInlined = getClassIdsInlined(classIds);
				makePostRequest(wrapper, schoolID, classIdsInlined, true);

				WebRequest webRequest = new WebRequest(SEARCH_URL);
				webRequest.setHttpMethod(HttpMethod.GET);

				Cookie cookie = new Cookie("www.textyard.com", "Campus_ID", schoolID);
				cookieMngr.addCookie(cookie);
				cookie = new Cookie("www.textyard.com", "Term_ID", Integer.toString(dept.getTerm().getId()));
				cookieMngr.addCookie(cookie);
				cookie = new Cookie("www.textyard.com", "class_searches", classIdsInlined);
				cookieMngr.addCookie(cookie);

				HtmlPage result = web.getPage(webRequest);
				books.addAll(processResults(result));
				makePostRequest(wrapper, classIdsInlined, classIdsInlined, false);
				int progress = 3;
				if (size / (i + 3) == 0) {
					if (i != 0) {
						progress = size % i;
					} else {
						progress = size;
					}
				}
				
				processedClasses += progress;
				status.postProgress((int) Math.ceil(progress * progressDelta / size));
			}
			resultMap.put(dept, books);
			System.out.println("Done for DEPT " + dept.getDepCode() + " took\t" + (System.currentTimeMillis() - start)
					/ 1000.0 + "sec");
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}

	}

	private void makePostRequest(final WebConnectionWrapper wrapper, final String schoolID, final String classIds,
			final boolean search) {
		long start = System.currentTimeMillis();
		URL url;
		if (search) {
			url = postSearchUrl;
			postSearchCount++;
			System.out.println("Making post SEARCH for \t\t" + classIds);
		} else {
			postRemoveCount++;
			url = postRemoveUrl;
		}
		try {
			WebRequest webRequest = new WebRequest(url);
			webRequest.setHttpMethod(HttpMethod.POST);
			List<NameValuePair> params = new ArrayList<NameValuePair>();
			String[] ids = classIds.split(COMMA_URL_CODE);
			for (int i = 0; i < ids.length; i++) {
				params.add(new NameValuePair("tokens[" + i + "][Class_ID]", String.valueOf(ids[i])));
			}
			if (search) {
				params.add(new NameValuePair("c", schoolID));
			}
			webRequest.setRequestParameters(params);
			WebResponse response = wrapper.getResponse(webRequest);
			if (response.getContentAsString().contains("pastLimit")) { // create new web client
				System.err.println("PAST LIMIT ERROR\nREQUEST COUNTERS: [" + postSearchCount + ", " + postRemoveCount
						+ "]");
				
				resultExporter.export(resultMap);
				resultMap.clear();
				// errorCount++;
				// if (errorCount == LIMIT) {
				// breakOperation = true;
				// status.postBreaking();
				// return;
				// }
				// useProxy = true;
//				status.postPastLimitError();

				// if (noMoreProxies) {
				status.postStatusIPBlocked();
				Thread.sleep(BLOCKED_TIMEOUT * 1000);
				// }

				createNewWebClient();
				postSearchCount = 0;
				postRemoveCount = 0;
				processedClasses = 0;
				makePostRequest(wrapper, schoolID, classIds, search);
			}
			System.out.println("Done makePostRequest\t took\t" + (System.currentTimeMillis() - start) / 1000.0 + "sec");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String getClassIdsInlined(final ArrayList<Integer> classIds) {
		String ids = "";
		if (classIds.size() == 0) {
			return ids;
		}
		// inline max of 3 ids
		for (int i = 0; i < 3; i++) {
			ids += String.valueOf(classIds.remove(0));
			if (!classIds.isEmpty() && i != 2) {
				ids += COMMA_URL_CODE;
			} else {
				break;
			}
		}
		return ids;
	}

	private ArrayList<Integer> getClassIds(final Department dept) {
		long start = System.currentTimeMillis();
		ArrayList<Integer> classIds = new ArrayList<Integer>();
		int coursesSize = dept.getCources().size();
		for (int i = 0; i < coursesSize; i++) {
			Course c = dept.getCources().get(i);
			String url = constructSessionUrl(dept, c);
			try {
				c.setSections(loadSectionForCourse(url));
				System.out.printf("Getting sections: %.2f%% done%n", (i + 1) * 1.0 / coursesSize * 100);
				Thread.sleep(500);
			} catch (NoHttpResponseException e) {
				System.err.println("NoHttpResponseException for " + c.getCourseCode());
				status.postErrorMsg("Server doesn't respond. Retrying...");
				continue;
			} catch (SocketTimeoutException e2) {
				System.err.println("SocketTimeoutException for " + c.getCourseCode());
				status.postErrorMsg("Server doesn't respond. Retrying...");
				e2.printStackTrace();
				continue;
			} catch (Exception e) {
				System.err.println("Exception for " + c.getCourseCode());
				e.printStackTrace();
			}
		}

		for (Course c : dept.getCources()) { // some sections can be null
			if (c.getSections() != null) {
				for (Section s : c.getSections()) {
					classIds.add(s.getId());
				}
			}
		}
		System.out.println("Done getClassIds\t took\t" + (System.currentTimeMillis() - start) / 1000.0 + " sec");
		return classIds;
	}

	private ArrayList<Book> processResults(final HtmlPage result) {
		ArrayList<Book> books = new ArrayList<Book>();
		Document doc = Jsoup.parse(result.asXml());
		Elements searchResults = doc.select("div[class=results_set]");
		for (Element el : searchResults) {
			String fullClassName = getFullClassName(el);
			Elements bookLists = el.select("div[class=results-list]");
			for (Element bookEl : bookLists) {
				books.add(createBook(bookEl, fullClassName));
			}
		}
		return books;
	}

	private Book createBook(final Element bookEl, final String fullClassName) {
		String bookName = "n/a";
		String required = "-";
		String authors = "n/a";
		String iSBN = "n/a";
		String edition = "n/a";
		String publisher = "n/a";
		String storePrice = "n/a";
		String lowestPrice = "n/a";
		try {
			Element bookInfo = bookEl.select("div[class=book-info]").get(0);
			bookName = bookInfo.getElementsByTag("h4").get(0).text();

			Elements metaInfos = bookInfo.select("ul[class=book-meta-info]");
			if (metaInfos.size() == 0) {
				metaInfos = bookEl.select("ul[class=book-meta-info-full]");
			}
			Elements metaInfoList = metaInfos.get(0).getElementsByTag("li");
			for (Element meta : metaInfoList) {
				String text = meta.text();
				if (text.contains("* Required")) {
					required = "*";
				} else if (text.contains("Authors: ")) {
					authors = text.replace("Authors: ", "");
				} else if (text.contains("ISBN: ")) {
					iSBN = text.replace("ISBN: ", "");
				} else if (text.contains("Edition: ")) {
					edition = text.replace("Edition: ", "");
				} else if (text.contains("Publisher: ")) {
					publisher = text.replace("Publisher: ", "");
				}
			}

			Elements prices = bookInfo.select("ul[class=book-prices]");
			if (prices.size() != 0) {
				Elements pricesList = prices.get(0).getElementsByTag("li");
				storePrice = pricesList.get(0).text().replace("Bookstore Price: ", "");
				lowestPrice = pricesList.get(2).text().replace("Lowest Price: ", "");
				if (storePrice.startsWith("$")) {
					storePrice = storePrice.substring(1);
				}
				if (lowestPrice.startsWith("$")) {
					lowestPrice = lowestPrice.substring(1);
				}
			} else {
				prices = bookInfo.select("ul[class=book-sellers-list]");
				if (prices.size() > 0) {
					Elements pricesList = prices.get(0).getElementsByTag("li");
					String text = pricesList.get(0).text();
					String replacementString;
					if (text.contains("Amazon")) {
						replacementString = "Buy from Amazon $";
					} else {
						replacementString = "Buy from EBay $";
					}
					String[] newUsedPrices = text.replace(replacementString, "")
							.split(" New, \\$");
					if (newUsedPrices.length == 2) {
						storePrice = newUsedPrices[0];
						lowestPrice = newUsedPrices[1].substring(0, newUsedPrices[1].indexOf(' '));
					}
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		Book book = new Book.Builder(fullClassName).iSBN(iSBN).required(required).name(bookName).authors(authors)
				.edition(edition).publisher(publisher).bookstorePrice(storePrice).lowestPrice(lowestPrice).build();
		return book;
	}

	private String getFullClassName(final Element el) {
		String text = el.getElementsByTag("h1").get(0).text();
		return text.substring(text.indexOf(" for ") + 5, text.indexOf('(') - 1);
	}

	private String getSessId() {
		try {
			URL url = new URL(link);
			WebConnectionWrapper w = new WebConnectionWrapper(web);
			WebResponse schoolResp = w.getResponse(new WebRequest(url));
			String cookies = schoolResp.getResponseHeaderValue("Set-Cookie");
			if (cookies != null) {
				String[] parts = cookies.split(";");
				for (int i = 0; i < parts.length; i++) {
					if (parts[i].contains("PHPSESSID")) {
						String[] pair = parts[i].split("=");
						return pair[1];
					}
				}
			}
		} catch (Exception ex) {

		}
		return "";
	}

	private String constructSessionUrl(final Department dept, final Course c) {
		return ajaxBase + dept.getTerm().getSchoolID() + "&term=" + dept.getTerm().getId() + "&dept=" + dept.getId()
				+ "&course=" + c.getId();
	}

	private void outputPage(final HtmlPage result) {
		try {
			PrintWriter writer = new PrintWriter("C:/DEMO/" + COUNT + ".html");
			writer.write(result.asXml());
			writer.flush();
			writer.close();
			COUNT++;
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private BrowserVersion getNextBrowserVersion() {
		if (browserIndex == browserVersionChain.length - 1) {
			browserIndex = 0;
		}
		return browserVersionChain[browserIndex++];
	}

	public TreeMap<Department, ArrayList<Book>> getResultMap() {
		return resultMap;
	}

	public StatusPostable getStatus() {
		return status;
	}

	public void setStatus(final StatusPostable status) {
		this.status = status;
	}

	public int getProcessedClasses() {
		return processedClasses;
	}

	public void setOutputFile(final String file) {
		outputFile = file;
		
	}
}
